﻿#include "componentmanager.h"
#include "system_log/systemjournal.h"
#include "createComponet.h"
#include "../systemconfig/systemconfig.h"
#include "common_log.h"


static ComponentManager* instance = nullptr;
ComponentManager* ComponentManager::GetInstance()
{
	if (instance == nullptr) {
		instance = new ComponentManager(nullptr);
	}
	return instance;
}


ComponentManager::ComponentManager(QObject *parent)
	: QObject(parent)
{
	m_writer = new SystemJournal();
}

ComponentManager::~ComponentManager()
{
}


// 创建组件
bool ComponentManager::Init(const QVector<ComponentType>& coms)
{
	m_components.clear();
	QVector<ComponentType> all;
	if (coms.size() <= 0) {
		all = CreateProjectComponent();
	} else {
		all = coms;
	}

	for (auto iter : all) {
		auto temp = CreateComponet(iter);
		if ( temp == nullptr) {
			m_errmsg = "组件类型不支持，无法创建";
			return false;
		} 
		QString param = sysCfg->GetConfig(iter);
		auto ret = temp->Init(param.toUtf8());
		if (ret == 0) {
			m_components.emplace(iter, temp);
			log_trace("{}:初始化成功", temp->GetComponentName());
		} else if (ret == IGNORE_ERROR){
			log_info("{}: 无需加载" , temp->GetComponentName());
			temp->deleteLater();
			temp = nullptr;
		} else {
			m_errmsg = temp->GetComponentErrMsg();
			log_error("{}: 加载失败-{}", temp->GetComponentName(), m_errmsg);
			temp->deleteLater();
			temp = nullptr;
			return false;
		}

	}

	return true;
}

bool ComponentManager::CheckComponent()
{
	m_errmsg.clear();
	if (m_components.size() <= 0) {
		m_writer->WriteErrorJournal(u8"未配置任何组件，组件检查失败");
		return false;
	}

	bool ret = true;
	for (auto& iter : m_components) {
		if (!iter.second->CheckState()) {
			log_error("component[{}] check error", (int)iter.first);
			m_errmsg += iter.second->GetComponentErrMsg() + "/";
			m_writer->WriteErrorJournal(m_errmsg);
			ret = false;
		}
	}
	return ret;
}
bool ComponentManager::ResetComponent()
{
	m_errmsg.clear();
	if (m_components.size() <= 0) {
		m_writer->WriteTraceJournal(u8"未配置任何组件，组件复位完成");
		return true;
	}

	bool ret = true;
	for (auto& iter : m_components) {
		if (!iter.second->Reset()) {
			log_error("component[{}] reset error", (int)iter.first);
			m_errmsg += iter.second->GetComponentErrMsg() + "/";
			m_writer->WriteErrorJournal(m_errmsg);
			ret = false;
		}
	}
	return ret;
}

/****************************************************************************
 * 功能: 获取组件
 * 传参: id: 组件类型， loaded: true 在列表中未找到组件时会自动重新加载组件， flase只从列表中获取
 * 返回值: 组件指针，获取失败为nullptr
 ****************************************************************************/
Component* ComponentManager::GetComponent(ComponentType id, bool load)
{
	if (m_components.find(id) == m_components.end() && load) {
		auto temp = CreateComponet(id);
		if (temp == nullptr) {
			m_errmsg = "组件类型不支持，无法创建";
			return nullptr;
		}
		QString param = sysCfg->GetConfig(id);
		auto ret = temp->Init(param.toUtf8());
		if (ret == 0) {
			m_components.emplace(id, temp);
			log_trace("{}:初始化成功", temp->GetComponentName());
			return temp;
		} else {
			m_errmsg = temp->GetComponentErrMsg();
			log_error("{}: 加载失败-{}", temp->GetComponentName(), m_errmsg);
			return nullptr;
		}		
	}
	if (m_components.find(id) == m_components.end()) {
		log_error("Component[{}] not created in the current period", (int)id);
		return nullptr;
	} else {
		return m_components[id];
	}
}
Component* ComponentManager::CreateNewComponent(ComponentType id)
{
	auto temp = CreateComponet(id);
	if (temp == nullptr) {
		return nullptr;
	}
	return temp;
}


Component* ComponentManager::GetComponentByStr(const QString& str)
{
	log_trace("get component by str[{}]", str);
	QMap<QString, ComponentType> comMapping = {
		//{"robot", Component::componet_robot},
	};

	if (comMapping.contains(str)) {
		auto id = comMapping.value(str);
		return GetComponent(id);
	}

	return nullptr;
}
QString ComponentManager::GetErrorMsg()
{
	QString str = m_errmsg;
	return str;
}

void ComponentManager::RegisterSystemEventCallBake(std::function<void(int)> callbake)
{
	m_sytemCall.append(callbake);
}

/****************************************************************************
 * 功能: 系统停止事件处理: 1. 发布系统事件（系统停止） 2.获取异常组件错误信息
 * 传参: id: 组件编号, eventid: 事件编号
 * 返回值:
 ****************************************************************************/
void ComponentManager::DealWithComponentSystemEvent(int id, int eventid)
{
	ComponentEvent event = (ComponentEvent)eventid;
	ComponentType type = (ComponentType)id;
	QString  str;
	switch (event) {
	case ComponentEvent::system_event_reset:
		str = "系统接收到复位信号";
		break;
	case ComponentEvent::system_event_start:
		str = "系统收到启动信号";
		break;
	case ComponentEvent::system_event_Enter:
		str = "系统收到请求进入信号";
		break;
	case ComponentEvent::system_event_stop:
		str = "系统收到停止信号";
		{
			auto com = GetComponent(type);
			if (com == nullptr) {
				m_errmsg = "组件获取失败, 停止原因未知";
				return;
			} else {
				m_errmsg = "停止原因：" + com->GetComponentErrMsg();
			}
			log_error("组件{}运行出错, {}", com->GetComponentName(), m_errmsg);
		}
		break;
	default:
		str = "系统收到未知信号";
		break;
	}
	m_writer->WriteTraceJournal(str);

	for (auto call : m_sytemCall) {
		call(eventid);
	}

	log_trace("id {} send a system event {}", id, eventid);
}

/****************************************************************************
 * 功能: 系统告警事件处理: 将异常信息告警显示
 * 传参: 组件编号componet， 告警信息：msg
 * 返回值:
 ****************************************************************************/
void ComponentManager::DealWithComponentWarningEvent(int id, const QString& msg)
{
	ComponentType type = (ComponentType)id;
	auto com = GetComponent(type);
	log_error("id {} send a warning msg: {}", id, msg);
	QString  str;
	if (com == nullptr) {
		log_error("id {} componet get failed");
		str += QString::number(id) + "告警:" + msg;
	} else {
		str += com->GetComponentName() + "告警:" + msg;
	}
	m_writer->WriteWarnJournal(str);
}

/****************************************************************************
 * 功能: 系统状态发布，向组件发布系统状态
 * 传参: 系统状态 state
 * 返回值:
 ****************************************************************************/
void ComponentManager::DealWithSystemEvent(int state)
{
	log_trace("system state = {}", state);
	for (auto iter : m_components) {
		iter.second->ResponseSystemState(state);
	}
}

